package org.jing.ext.extra;

import org.jing.core.lang.ExceptionHandler;
import org.jing.core.util.DateUtil;
import org.jing.core.util.StringUtil;

import java.util.Calendar;
import java.util.Date;

/**
 * Description: <br>
 *
 * @author bks <br>
 * @since 2021-07-01 <br>
 */
public class PersonUtil {
    private static final int[] ID_CARD_RATIO = {7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2};

    private static final int[] ID_CARD_SUFFIX = {1, 0, 10, 9, 8, 7, 6, 5, 4, 3, 2};

    /**
     * Description: 校验身份证号码格式. <br>
     *
     * @param idCardNumber 身份证号码 <br>
     * @return null则代表校验成功, 否则输出校验错误信息 <br>
     */
    public static String validatePersonIdCardNumber(String idCardNumber) {
        if (idCardNumber == null || idCardNumber.length() != 18) {
            return "Invalid id card number length";
        }
        idCardNumber = idCardNumber.toUpperCase();
        if (!idCardNumber.matches("\\d{17}[X|\\d]")) {
            return "Invalid id card number";
        }
        // 大概校验格式
        String provinceCode = idCardNumber.substring(0, 2);

        String cityCode = idCardNumber.substring(2, 4);

        String areaCode = idCardNumber.substring(4, 6);

        int birthdayYear = StringUtil.parseInteger(idCardNumber.substring(6, 10));
        if (birthdayYear < 1800) {
            return "Invalid id card number birthday";
        }

        int birthDayMonth = StringUtil.parseInteger(idCardNumber.substring(10, 12));
        if (birthDayMonth < 1 || birthDayMonth > 12) {
            return "Invalid id card number birthday";
        }

        int birthDayDate = StringUtil.parseInteger(idCardNumber.substring(12, 14));
        int[] days = {31, birthdayYear % 100 != 0 && birthdayYear % 4 == 0 || birthdayYear % 400 == 0 ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        if (birthDayDate < 0 || birthDayDate > days[birthDayMonth - 1]) {
            return "Invalid id card number birthday";
        }


        String unitCode = idCardNumber.substring(14, 16);

        String sexCode = idCardNumber.substring(16, 17);

        // 检查末尾校验位
        int result = 0;
        for (int i$ = 0; i$ < 17; i$++) {
            result += ID_CARD_RATIO[i$] * (idCardNumber.charAt(i$) - '0');
        }
        result = ID_CARD_SUFFIX[result % 11];
        int suffix = idCardNumber.charAt(17);
        if ('X' == suffix) {
            suffix = 10;
        }
        else {
            suffix -= '0';
        }
        if (suffix != result) {
            return "Invalid id card number check suffix";
        }

        return null;
    }

    /**
     * Description: 计算周岁 <br>
     *
     * @param birthDate 生日 <br>
     * @param nowDate 当前时间 <br>
     * @return <br>
     */
    public static int calculateAge(Date birthDate, Date nowDate) {
        ExceptionHandler.publishIfMatch(birthDate.after(nowDate), "now data should after birth date");
        Calendar birthC = Calendar.getInstance();
        birthC.setTime(birthDate);
        Calendar nowC = Calendar.getInstance();
        nowC.setTime(nowDate);
        int birthYear = birthC.get(Calendar.YEAR);
        int birthMonth = birthC.get(Calendar.MONTH);
        int birthDay = birthC.get(Calendar.DATE);
        int nowYear = nowC.get(Calendar.YEAR);
        int nowMonth = nowC.get(Calendar.MONTH);
        int nowDay = nowC.get(Calendar.DATE);
        return nowYear - birthYear - 1 + (nowMonth > birthMonth ? 1  : nowMonth < birthMonth ? 0 : nowDay >= birthDay ? 1 : 0);
    }

    public static void main(String[] args) throws Exception {
        System.out.println(PersonUtil.calculateAge(
            DateUtil.getDate("19960523", "yyyyMMdd"), DateUtil.getDate("19980523", "yyyyMMdd")));
    }
}
